package itsec1.api.services;



import itsec1.api.cardmanagement.CardManagementCaller;
import itsec1.customermanagement.CustomerDAO;
import itsec1.customermanagement.CustomerManagement;
import itsec1.customermanagement.UserDAO;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSocket;



public class ServiceRequestHandler implements Runnable {
	private CustomerManagement cm;
	private SSLSocket socket;
		
	public ServiceRequestHandler(CustomerManagement cm, Socket socket) {
		this.cm = cm;
		this.socket = (SSLSocket) socket;		
	}
	
	@Override
	public void run() {
		boolean authenticated= false;
		boolean requestDenied= true;
		boolean isCustomerRequest= false;
		//initialized with no rights
		AllowedRequests rights= new AllowedRequests();
		
		try {
            BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            
            //expected request format for methods: 
            //  methodname;username;password;parameter1;parameter2;... 
            String request= in.readLine();
            
            String serviceName= this.socket.getSession().getPeerPrincipal().getName();
            
            String[] split= request.split(";");
            String result=null;
                        
            if(split.length >= 3)
            {
            	 //if request comes from selfmangement -> special treatment (because user = customer)
	            if(serviceName.startsWith("CN=selfManager")){
	            	authenticated= CustomerDAO.autenticateCustomer(cm, split[1], split[2], split[3]);	            	
	            	isCustomerRequest= true;
	            }else{
	            	//other services -> require authentification with user from user-table
	            	rights= UserDAO.authenticateUser(cm, split[1], split[2]);
	            	
	            	if(rights != null)
	            		authenticated= true;
	            }
            }
	        
            if(authenticated){            	
            	//GET-METHODS
            	if(isCustomerRequest || rights.isReadPersonalData()){
		            if(split[0].equals("getFirstName")){
		            	result= CustomerDAO.getField(cm,"firstname", split[3]);
		            	requestDenied= (result==null)? true : false;
		            }else if(split[0].equals("getLastName")){
		            	result= CustomerDAO.getField(cm,"lastname", split[3]);
		            	requestDenied= (result==null)? true : false;
		            }else if(split[0].equals("getSex")){
		            	result= CustomerDAO.getField(cm,"sex", split[3]);
		            	requestDenied= (result==null)? true : false;
		            }
            	}
            	if(isCustomerRequest || rights.isReadAddressData()){
		            if(split[0].equals("getZipcode")){		            	
		            	result= CustomerDAO.getField(cm,"zipcode", split[3]);
		            	requestDenied= (result==null)? true : false;
		            }else if(split[0].equals("getAddress")){
		            	result= CustomerDAO.getField(cm,"address", split[3]);
		            	requestDenied= (result==null)? true : false;
		            }
            	}
            	if(isCustomerRequest || rights.isReadContactData()){
		            if(split[0].equals("getEmail")){
		            	result= CustomerDAO.getField(cm,"email", split[3]);
		            	requestDenied= (result==null)? true : false;
		            }else if(split[0].equals("getPhone")){
		            	result= CustomerDAO.getField(cm,"phone", split[3]);
		            	requestDenied= (result==null)? true : false;
		            }
            	}
            	if(isCustomerRequest || rights.isReadPassword()){
		            if(split[0].equals("getPassword")){
		            	result= CustomerDAO.getField(cm,"password", split[3]);
		            	requestDenied= (result==null)? true : false;
		            }
            	}
            	if(isCustomerRequest || rights.isReadClosedData()){
		            if(split[0].equals("getClosed")){
		            	result= CustomerDAO.getField(cm,"closed", split[3]);
		            	requestDenied= (result==null)? true : false;
		            }else if(split[0].equals("getClosedDate")){
		            	result= CustomerDAO.getField(cm,"closedate", split[3]);
		            	requestDenied= (result==null)? true : false;
		            }
            	}
            	if(isCustomerRequest || rights.isReadCardData()){
		            if(split[0].equals("getCardLimit")){
		            	result= relayCardRequest(split);
		            	requestDenied= (result==null)? true : false;
		            }else if(split[0].equals("getCardNumbers")){
		            	result= relayCardRequest(split);
		            	requestDenied= (result==null)? true : false;
		            }else if(split[0].equals("isValid")){
		            	result= relayCardRequest(split);
		            	requestDenied= (result==null)? true : false;
		            }
            	}
            	//WRITE-METHODS
            	//personal data
            	if(rights.isWritePersonalData()){
            		if(split[0].equals("setFirstName")){
            			requestDenied= !CustomerDAO.setField(cm,"firstname",split[3],split[4]);
    		        }else if(split[0].equals("setLastName")){
    		            requestDenied= !CustomerDAO.setField(cm,"lastname", split[3],split[4]);
    		        }else if(split[0].equals("setSex")){
    		            requestDenied= !CustomerDAO.setField(cm,"sex", split[3],split[4]);
    		        }
                }
            	//address data
            	if(rights.isWriteAddressData()){
		            if(split[0].equals("setZipcode")){
		            	requestDenied= !CustomerDAO.setField(cm,"zipcode", split[3],split[4]);
		            }else if(split[0].equals("setAddress")){
		            	requestDenied= !CustomerDAO.setField(cm,"address", split[3],split[4]);
		            }
            	}
            	//contact data
            	if(isCustomerRequest || rights.isWriteContactData()){
		            if(split[0].equals("setEmail")){
		            	requestDenied= !CustomerDAO.setField(cm,"email", split[3],split[4]);
		            }else if(split[0].equals("setPhone")){
		            	requestDenied= !CustomerDAO.setField(cm,"phone", split[3],split[4]);
		            }
            	}
            	//password
            	if(rights.isWritePasswordData()){
		            if(split[0].equals("setPassword")){
		            	requestDenied= !CustomerDAO.setField(cm,"password", split[3],split[4]);
		            }
            	}
            	//delete customer
            	if(rights.isDeleteCustomer()){
		            if(split[0].equals("deleteCustomer")){
		            	requestDenied= !CustomerDAO.deleteCustomer(cm,split[3]);
		            }
            	}
            	//insert customer
            	if(rights.isInsertCustomer()){
            		if(split[0].equals("insertCustomer")){
		            	Integer id= CustomerDAO.insertCustomer(cm, 
		            			split[3], split[4], split[5], split[6], split[7]
		            			 , split[8], split[9], split[10], split[11], split[12], split[13], split[14]);
		            	
		            	if(id == null)
		            		requestDenied= true;
		            	else{
		            		result= ""+id.intValue();
		            		requestDenied= false;
		            	}
		            }
            	}
            	//card limit
            	if(isCustomerRequest || rights.isWriteCardLimitData()){
		            if(split[0].equals("setCardLimit")){
		            	result= relayCardRequest(split);
		            	if(result != null && result.equals("true"))
		            		requestDenied= false;
		            }
            	}
            	//delete card
		        if(rights.isDeleteCard()){
		            if(split[0].equals("deleteCard")){
		            	result= relayCardRequest(split);
		            	if(result != null && result.equals("true"))
		            		requestDenied= false;
		            }
            	}
		        //insert card
            	if(rights.isInsertCard()){
		            if(split[0].equals("insertCard")){
		            	result= relayCardRequest(split);
		            	if(result != null && result.equals("true"))
		            		requestDenied= false;
		            }
            	}            	
            	//register user
            	if(rights.isRegisterUser()){
	            	if(split[0].equals("registerUser")){
	            		requestDenied= !UserDAO.registerUser(cm, split[3], split[4], split[5]);
	            	}
            	}
            	//unregister user
            	if(rights.isUnregisterUser()){
	            	if(split[0].equals("unregisterUser")){
	            		requestDenied= !UserDAO.unregisterUser(cm, split[3]);
	            	}
            	}
            }

            if(requestDenied)
            	result= "Request denied";           	       
            
            if(result != null){            
	            out.write(result);
	        	out.newLine();
	        	out.flush();
            }else{
            	//return success in cases where a set/register/unregister request was successful
            	out.write("true");
	        	out.newLine();
	        	out.flush();
            }
        }catch(SSLHandshakeException e){
        	System.out.println("Service request rejected due to unkown certificate being used by "+socket.getInetAddress()+":"+socket.getPort());
        }catch(Exception e) {
            System.out.println("Error: " + e.getMessage());
            e.printStackTrace();
        } // catch
        try {
            socket.close();
        } catch ( Exception e ) {}
	}
	
	private String relayCardRequest(String[] request){
		String cardRequest=request[0];
		for(int i=3; i < request.length; i++)
			cardRequest+= ";"+request[i];
		
		return CardManagementCaller.sendRequest(cardRequest);
	}
}
